use std::{str::FromStr,fmt::{self}};

use clap::Parser;

use crate::cli::verify_input_filename;


#[derive(Debug, Parser)]
pub enum Base64SubCommand {
    #[command(name = "encode", about = "Base64 encode")]
    Encode(Base64Opts),
    #[command(name = "decode", about = "Base64 decode")]
    Decode(Base64Opts),
   

}

#[derive(Debug, Parser)]
pub struct Base64Opts {
    #[arg(short, long, value_parser = verify_input_filename, default_value = "-")] // "-" 代表 从 标准输入 读取
    pub input: String,

    #[arg(short, long, default_value = "standard", value_parser = verify_base64_format)]
    pub format: Base64Format,
    
}

#[derive(Debug, Parser,Clone, Copy)]
pub enum Base64Format {
    Standard,
    UrlSafe,
}

fn verify_base64_format(format: &str) -> Result<Base64Format, &'static str> {
    match format.to_lowercase().as_str() {
        "standard" => Ok(Base64Format::Standard),
        "urlsafe" => Ok(Base64Format::UrlSafe),
        _ => Err("Invalid base64 format. Use 'standard' or 'urlsafe'."),
    }
}

impl FromStr for Base64Format {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        verify_base64_format(s)
    }
}

impl From<Base64Format> for &'static str {
    fn from(format: Base64Format) -> Self {
        match format {
            Base64Format::Standard => "standard",
            Base64Format::UrlSafe => "urlsafe",
        }
    }
}

impl fmt::Display for Base64Format {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let format_str = match self {
            Base64Format::Standard => "standard",
            Base64Format::UrlSafe => "urlsafe",
        };
        write!(f, "{}", format_str)
    }
    // fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    //     write!(f,"{}",Into::<&'static str>::into(*self))
    // }
}


// rust 下面标准的 trait， 会为后来的实现提供默认实现， standard 里有 64 个 trait
// https://doc.rust-lang.org/std/str/trait.FromStr.html
// https://doc.rust-lang.org/std/fmt/trait.Display.html
// https://doc.rust-lang.org/std/convert/trait.From.html
